#include "../lib/coreploader.hpp"
#include <fstream>
#include <vector>
#include <dlfcn.h>
#include <cstdlib>
#include <cstdio>
#include "../lib/coreutil.hpp"

using namespace pland;

Plugin * PLoader::loadPlugin(std::string path, Plugin_Id id)
{
    char *error;
    void * library_handle;
    UserC_Plugin * userPlugin = NULL;
    Plugin * corePlugin = NULL;
	void* (*_setup)(void);
    void (*_wrapup)(UserC_Plugin*);
    if(!util_fexists(path))
    {
        utill_log(std::string(__FILE__) +" Plugin path \"" + path + "\" does not exist.");
        return NULL;
    }
    library_handle = dlopen(path.c_str(), RTLD_LAZY);
    if ((error = dlerror()) != NULL || library_handle == NULL)
    {
        utill_log(std::string(__FILE__) +" Plugin path \"" + path + "\" Could not be opened: " + error);
        return NULL;
    }
	_setup = (void* (*)(void))dlsym(library_handle, "Core_GetInstance");
    if ((error = dlerror()) != NULL || _setup == NULL)
    {
        utill_log(std::string(__FILE__) +" Plugin path \"" + path + "\" Could not get the constructor function: " + error);
        goto out;
    }
    _wrapup = (void (*)(UserC_Plugin*))dlsym(library_handle, "Core_KillInstance");
    if ((error = dlerror()) != NULL || _wrapup == NULL)
    {
        utill_log(std::string(__FILE__) +" Plugin path \"" + path + "\" Could not get the destructor function: " + error);
        goto out;
    }
    utill_log(std::string(__FILE__) +" loaded");

	userPlugin = (UserC_Plugin*)_setup();
    if(userPlugin == NULL)
    {
        utill_log(std::string(__FILE__) +" Plugin path \"" + path + "\" Could not create a plugin instance");
        goto out;
    }
    corePlugin = new Plugin(userPlugin, _wrapup, id);

    return corePlugin;
    out:
        dlclose(library_handle);
        return NULL;
}
